/*
 *   Copyright 1999-2016 Asiainfo Technologies(China),Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

package com.asiainfo.redis.web.controller;

import com.asiainfo.redis.entity.Cluster;
import com.asiainfo.redis.entity.Host;
import com.asiainfo.redis.entity.Result;
import com.asiainfo.redis.service.HostService;
import com.asiainfo.redis.service.RedisService;
import com.asiainfo.redis.web.PageData;
import com.asiainfo.redis.web.PageParameter;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;

/**
 * @version v 1.0 on 2016/3/3 14:14
 * @auther william.xu
 */

@RestController
@RequestMapping("/redis-api")
public class RedisController extends BaseController {

    protected static final Logger LOGGER = LoggerFactory.getLogger(RedisController.class);

    @Resource
    private RedisService redisService;

    @Resource
    private HostService hostService;

    @RequestMapping("/saveHost")
    public Result saveHost(Host redisHost) throws Exception {
        Result result = new Result();
        hostService.saveHost(redisHost);
        return result;
    }

    @RequestMapping("/getHosts")
    public PageData getHosts(@RequestParam(value = "search", required = false) String ipKey, PageParameter
            pageParameter) {
        Page data = hostService.getHostList(ipKey, pageParameter.getPageable());
        return new PageData(data);
    }

    @RequestMapping("/getClusters")
    public Result getClusterList(boolean isMasterClusterOnly) {
        Result result = new Result();
        result.setResult(redisService.getClusterList(isMasterClusterOnly));
        return result;
    }

    @RequestMapping(value = "/newCluster", method = RequestMethod.POST)
    public Result newCluster(@RequestBody Cluster cluster) throws Exception {
        LOGGER.info("newCluster=" + cluster);
        Result result = new Result();
        redisService.newCluster(cluster);
        return result;
    }

    @RequestMapping(value = "/addNodesToCluster", method = RequestMethod.POST)
    public Result addNodesToCluster(@RequestBody Cluster cluster) throws Exception {
        LOGGER.info("addNodesToCluster=" + cluster);
        Result result = new Result();
        redisService.addNodesToCluster(cluster);
        return result;
    }

    @RequestMapping(value = "/removeNodeFromCluster")
    public Result removeNodeFromCluster(@RequestParam(required = true) Long nodeId) throws Exception {
        Result result = new Result();
        redisService.removeNodeFromCluster(nodeId);
        return result;
    }

    @RequestMapping(value = "/migrateSlots")
    public Result migrateSolts(@RequestParam(required = true) Long clusterId, @RequestParam(required = true) Long
            fromNodeId, @RequestParam(required = true) Long toNodeId, @RequestParam(required = true) Integer
            slotsNum) throws Exception {
        Result result = new Result();
        redisService.migrateSlots(clusterId, fromNodeId, toNodeId, slotsNum);
        return result;
    }

    @RequestMapping("/getClusterAndNodesInfo")
    public Result getClusterAndNodesInfo(@RequestParam(required = true) Long clusterId) throws Exception {
        Result result = new Result();
        result.setResult(redisService.getClusterAndNodesInfo(clusterId));
        return result;
    }

    @RequestMapping("/operClusterNode")
    public Result operClusterNode(@RequestParam(required = true) Long nodeId, @RequestParam(required = true) Boolean
            isStart) throws Exception {
        Result result = new Result();
        hostService.operClusterNode(nodeId, isStart);
        return result;
    }

    @RequestMapping("/getKeysBySlot")
    public Result<List<String>> getKeysBySlot(@RequestParam(required = true) Integer slot, @RequestParam(required =
            true) Long clusterId) throws Exception {
        Result<List<String>> result = new Result<List<String>>();
        result.setResult(redisService.getKeysBySlot(slot, clusterId));
        return result;
    }

    @RequestMapping("/getkeysByKeyQuery")
    public Result<List<Map>> getkeysByKeyQuery(@RequestParam(required = true) String key, @RequestParam(required =
            true) Long clusterId) throws Exception {
        Result<List<Map>> result = new Result();
        result.setResult(redisService.getkeysByKeyQuery(key, clusterId));
        return result;
    }

    @RequestMapping("/getValueByKey")
    public Result<Map> getValueByKey(@RequestParam(required = true) String key, @RequestParam(required = true)
            Long clusterId) throws Exception {
        Result<Map> result = new Result<Map>();
        result.setResult(redisService.getValueByKey(key, clusterId));
        return result;
    }

    @RequestMapping("/setValueByKey")
    public Result<String> setValueByKey(@RequestParam(required = true) String key,
                                        @RequestParam(required = true) String value,
                                        @RequestParam(required = true) Long clusterId) throws Exception {
        Result result = new Result();
        redisService.setValueByKey(key, encodedString2Map(value), clusterId);
        return result;
    }

    @RequestMapping("/getConnectedClients")
    public Result getConnectedClients(@RequestParam(required = true) Long clusterId) throws Exception {
        Result result = new Result();
        result.setResult(redisService.getConnectedClients(clusterId));
        return result;
    }

    @RequestMapping("/getUsedMemory")
    public Result getUsedMemory(@RequestParam(required = true) Long clusterId) throws Exception {
        Result result = new Result();
        result.setResult(redisService.getUsedMemory(clusterId));
        return result;
    }

    @RequestMapping("/getUsedMemoryRss")
    public Result getUsedMemoryRss(@RequestParam(required = true) Long clusterId) throws Exception {
        Result result = new Result();
        result.setResult(redisService.getUsedMemoryRss(clusterId));
        return result;
    }

    @RequestMapping("/getUsedCpuSys")
    public Result getUsedCpuSys(@RequestParam(required = true) Long clusterId) throws Exception {
        Result result = new Result();
        result.setResult(redisService.getUsedCpuSys(clusterId));
        return result;
    }

    @RequestMapping("/getUsedCpuUser")
    public Result getUsedCpuUser(@RequestParam(required = true) Long clusterId) throws Exception {
        Result result = new Result();
        result.setResult(redisService.getUsedCpuUser(clusterId));
        return result;
    }

    @RequestMapping("/getInfo")
    public Result getInfo(@RequestParam(required = true) Long clusterId, @RequestParam(required = true) String
            properties) throws Exception {
        Result result = new Result();
        result.setResult(redisService.getInfo(clusterId, properties));
        return result;
    }


    @RequestMapping(value = "/promoteMaster")
    public Result promoteMaster(@RequestParam(required = true) Long nodeId, boolean isForce) throws Exception {
        Result result = new Result();
        redisService.promoteMaster(nodeId, isForce);
        return result;
    }

    @RequestMapping(value = "/configSet")
    public Result configSet(@RequestParam(required = true)String param, @RequestParam(required = true)String value, @RequestParam(required = true) Long nodeId) throws Exception {
        Result result = new Result();
        redisService.configSet(param, value, nodeId);
        return result;
    }

    @RequestMapping(value = "/replicaMigration")
    public Result replicaMigration(@RequestParam(required = true, value = "slaveNodeId") Long id,
                                   @RequestParam(required = true, value = "masterNodeId") String nodeId)
            throws Exception {
        Result result = new Result();
        redisService.replicaMigration(id, nodeId);
        return result;
    }

    @RequestMapping(value = "/getStandbyClusterList")
    public Result getStandbyClusterList(@RequestParam(required = true, value = "clusterId") Long clusterId)
            throws Exception {
        Result result = new Result();
        result.setResult(redisService.getStandbyClusterList(clusterId));
        return result;
    }

    @RequestMapping(value = "/setStandbyCluster")
    public Result setStandbyCluster(@RequestParam(required = true)Long clusterId,
                                    @RequestParam(required = true)Long standbyId)
            throws Exception {
        Result result = new Result();
        redisService.setStandbyCluster(clusterId, standbyId);
        return result;
    }


}
